﻿#include "map_logic.h"
#include "MapServer.h"
#include "ManagerHelper.h"
#include "../share/MessageDef.h"
#include "obj_define.h"
//#include "script_define.h"
//#include "MapSlot.h"
#include "entity_define.h"
#include "../share/proxyclient_service.h"
#include "map_playermgr.h"
#include "mapobj_manager.h"
#include "scene_manager.h"
#include "UpdatePlayerBroadcast.h"
#include "skill_func.h"
#include "map_playermgr.h"

enum change_type
{
	tp_change_hero_id = 1,		//更换主英雄ID
	tp_change_name,				//更换名字
	tp_change_union_id,			//更换联盟ID
	tp_change_union_name,		//更换联盟名字
	tp_change_pet_id,			//更换宠物ID
	tp_change_mounts_id,		//更换坐骑ID
	tp_change_hero_skin_id,		//更换主英雄皮肤ID
	tp_change_level				//更换等级
};

void CMapLogic::Initialize()
{
	registe_client_msg(lua_general_message_req, CMapLogic::SGeneralLuaMessageReq);
	registe_client_msg(player_walk, CMapLogic::SPlayerWalkInfo);
	registe_client_msg(s_player_load_scene_finished, CMapLogic::SPlayerLoadSceneFinished);
	registe_client_msg(s_player_change_scene, CMapLogic::SPlayerChangeScene);
	//registe_client_msg(player_map_ping_req, CMapLogic::SPing);//player_ping_req
	registe_client_msg(s_notify, CMapLogic::SNotify);
	registe_client_msg(login_player_quit_game_notify, CMapLogic::SLoginPlayerQuitGameNotify);
	registe_client_msg(gate_close_client_fd_req, CMapLogic::SLoginPlayerQuitGameNotify);
	registe_client_msg(s_lose_blood_req, CMapLogic::SLoseBlood);
	registe_client_msg(s_player_revive_req, CMapLogic::SPlayerRevive);
	registe_client_msg(player_heal_req, CMapLogic::SHeal);

	registe_server_msg(map_player_change_something_notify, CMapLogic::SChangePlayerSomethingNotify);
	registe_server_msg(lua_general_message_req, CMapLogic::SGeneralLuaMessageReqServer);
	registe_server_msg(G2M_PLAYER_PET_STATUS_CHANGE_REQUEST, CMapLogic::SChangePlayerPetStatus);
	// G2M_PLAYER_HERO_INFO_CHANGE_REQUEST game 加载时map 可能未启动好服务 所以前面几次执行 是失败的
	registe_server_msg(G2M_PLAYER_HERO_INFO_CHANGE_REQUEST, CMapLogic::OnMsgPlayerHeroInfoChangeRequest);
	registe_server_msg(G2M_HEART_REQUEST, CMapLogic::OnMsgG2MHeartRequest);
	registe_server_msg(G2M_SEND_PLAYER_LOGIN_INFO, CMapLogic::OnMsgSendPlayerLoginInfo);
	registe_server_msg(g_map_player_login_req, CMapLogic::PlayerLoginAgainReq);
	registe_server_msg(player_map_ping_req, CMapLogic::SPingFromGame);//player_ping_req
}

void CMapLogic::SGeneralLuaMessageReq(Player& player, const CJsonMessageBase& msg)
{
	LOG_ERROR("default", "map server cant do lua message!");
}

void CMapLogic::SGeneralLuaMessageReqServer(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	LOG_ERROR("default", "map server cant do lua message!");
}

void CMapLogic::SPlayerWalkInfo(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;
	const Json::Value& m_jv = msg.GetJsonValue();

	uint32_t testPlayerId = player.GetPlayerId();

	if (PlayerState::ps_pre_enter_scene == player.GetPlayerState())
	{
		LOG_DEBUG("default", ">> step_return: pplayer [%d] state is ps_pre_enter_scene.", testPlayerId);
		return;
	}

	if (!m_jv.isMember("msgid"))
	{
		LOG_WARN("default", ">> step_return: msgid error.");
		return;
	}
	// game主城不处理位移
	if (player.GetSceneId() < 20100)
	{
		//return;
	}

	uint32_t _key = m_jv["ky"].asUInt();

	double _posX = m_jv["px"].asDouble();
	double _posY = m_jv["py"].asDouble();
	double _posZ = m_jv["pz"].asDouble();

	double _oX = m_jv["ox"].asDouble();
	double _oY = m_jv["oy"].asDouble();
	double _oZ = m_jv["oz"].asDouble();

	CSceneInstance* ins = CSceneManager::GetInstance().GetSceneInstance(player.instance_id());
	if (ins == NULL)
	{
		LOG_WARN("default", ">> step_return: pplayer [%d] map pointer is null.", testPlayerId);
		return;
	}
	player.set_orientation(_oX, _oY, _oZ);
	::common::CVector3 dst_pos(_posX, _posY, _posZ);
	ins->MoveEntity(player, dst_pos);
	ins->BroadcastPosition(player, player.GetPlayerId(), 0);
	return;

	_safe_guard_end;
}

void CMapLogic::SPlayerLoadSceneFinished(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	LOG_DEBUG("default", "Game Server: SPlayerLoadSceneFinished start.");
	const Json::Value& m_jv = msg.GetJsonValue();

	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _ai = m_jv["ai"].asUInt();
	uint32_t _si = m_jv["si"].asUInt();

	// 客户端控制的副本
	if (_si >= (uint32_t)SCENE_MAP_ID::CLIENT_SCENE_ID_BEGIN) {
		player.sendPlayerLoadSceneFinished();
		return;
	}

	player.LoadSceneFinished();

	LOG_DEBUG("default", "Game Server: SPlayerLoadSceneFinished over.");

	_safe_guard_end;
}

void CMapLogic::SPlayerChangeScene(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	LOG_DEBUG("default", "Map Server: SPlayerChangeScene start.");
	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _from = m_jv["fr"].asUInt();
	uint32_t _to = m_jv["to"].asUInt();
	int32_t _flag = m_jv["fl"].asInt();

	//	1：区域内检查的自动跳转
	//	2：指定跳转
	if (1 != _flag && 2 != _flag)
	{
		return;
	}

	if (CSceneManager::GetInstance().ChooseSceneForClient(player, m_jv)) {
		return;
	}
	int32_t ret_code = 0;
	player.SyncHeroGame2Map(0);
	if (!CSceneManager::GetInstance().CheckSceneChange(player, _to)) {
		return ;
	}

	::common::CVector3 dst_pos;
	
	CSceneInstance* ins = CSceneManager::GetInstance().AutoChooseScene(_to, dst_pos);
	if (ins == NULL)
	{
		LOG_ERROR("default", "player change scene err! from[%d], to[%d], flag[%d]", _from, _to, _flag);
		return;
	}
	CSceneInstance* old_ins = CSceneManager::GetInstance().GetSceneInstance(player.instance_id());
	if (NULL != old_ins)
	{
		old_ins->PlayerLeave(player);
		player.last_pos_.set_x(player.position().x());
		player.last_pos_.set_y(player.position().y());
		player.last_pos_.set_z(player.position().z());
		player.Send2CLevelScene(player.GetSceneId());
	}
	//这地方一定要先给玩家发送切换场景的回复，先这么做，很蛋疼
	player.set_position(dst_pos);
	player.set_instance_id(ins->instance_id());
	player.vision_link().SetBroadNum(20);

	//	ins->PlayerEnter(player, dst_pos, 0);
	player.Send2CEnterScene(player.GetSceneId(), ret_code);

	LOG_DEBUG("default", "Map Server: SPlayerChangeScene over.");

	_safe_guard_end;
}

void CMapLogic::SPing(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _key = m_jv["key"].asUInt();
	uint32_t _ch = m_jv["ch"].asUInt();
	uint32_t _cl = m_jv["cl"].asUInt();

	player.SetPingTime(_ch, _cl);

	_safe_guard_end;
}

void CMapLogic::SNotify(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;
	const Json::Value& m_jv = msg.GetJsonValue();
	
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _flag = m_jv["fl"].asUInt();
	std::string _ni = m_jv["ni"].asString();

//	player.NotifyAsFlag(_flag, _ni);

	_safe_guard_end;
}

void CMapLogic::SLoginPlayerQuitGameNotify(Player& player, const CJsonMessageBase& msg)
{
	CSceneInstance* instance = CSceneManager::GetInstance().GetSceneInstance(player.instance_id());
	if ( instance != NULL )
	{
		instance->PlayerLeave(player);
	}
	CMapPlayerManger::GetInstance().PlayerLeaveGame(player);
}

void CMapLogic::SChangePlayerSomethingNotify(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	_safe_guard_begin;
	const Json::Value m_jv = msg.GetJsonValue();
	LOG_DEBUG("default","game 2 Map server SChangePlayerSomethingNotify start.");
	int32_t playerId = m_jv["playerId"].asInt();
	int32_t gate_fd = m_jv["_gate_fd"].asInt();
	uint32_t flag = m_jv["flag"].asUInt();
	uint32_t send_flg = 0;

	Player * player = CMapPlayerManger::GetInstance().GetPlayerByPlayerID(playerId);
	
	if (player == NULL) {
		return;
	}
	flag &= ~uint32_t(UpdatePlayerInfoType::Hp);

	if (flag == 0) {
		return;
	}

	if (flag & uint32_t(UpdatePlayerInfoType::heroId)) {
		player->SetHeroId(m_jv["HeroId"].asUInt());
		player->SyncHeroGame2Map(m_jv["HeroId"].asUInt());
		send_flg |= uint32_t(UpdatePlayerInfoType::heroId);
		
	}
		/*
	case tp_change_name:
		player->SetName(m_jv["arg2"].asString().c_str());
		break;
		*/
	if (flag & uint32_t(UpdatePlayerInfoType::unionId)) {
		player->SetUnionId(m_jv["UnionId"].asUInt());
		send_flg |= uint32_t(UpdatePlayerInfoType::unionId);
	}

	if (flag & uint32_t(UpdatePlayerInfoType::unionName)) {
		player->SetUnionName(m_jv["UnionName"].asString().c_str());
		send_flg |= uint32_t(UpdatePlayerInfoType::unionName);
	}
	
	if (flag & uint32_t(UpdatePlayerInfoType::pet)) {
		player->SetPetId(m_jv["PetId"].asUInt());
		send_flg |= uint32_t(UpdatePlayerInfoType::pet);
	}
	
	if (flag & uint32_t(UpdatePlayerInfoType::mount)) {
		player->SetMountsId(m_jv["MountsId"].asUInt());
		player->SetMountsState(m_jv["MountsState"].asUInt());
		send_flg |= uint32_t(UpdatePlayerInfoType::mount);
	}
	
	
	if (flag & uint32_t(UpdatePlayerInfoType::heroSkinId)) {
		player->SetHeroSkinId(m_jv["HeroSkinId"].asUInt());
		send_flg |= uint32_t(UpdatePlayerInfoType::heroSkinId);
	}
	
	if (flag & uint32_t(UpdatePlayerInfoType::Exp)) {
		player->SetLevel(m_jv["Level"].asUInt());
		send_flg |= uint32_t(UpdatePlayerInfoType::Exp);
	}
	

	UpdatePlayerBroadcast& up_player_broad = player->GetUpdatePlayerBroadcast();
	up_player_broad.HandleBroadcastAoi(player, send_flg);

	LOG_DEBUG("default","Map server SChangePlayerSomethingNotify end.");

	_safe_guard_end;
}

void CMapLogic::SChangePlayerPetStatus(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	_safe_guard_begin;
	const Json::Value& m_jv = msg.GetJsonValue();
	uint32_t account = m_jv["account"].asUInt();
	uint32_t playerid = m_jv["playerId"].asUInt();
	uint32_t types = m_jv["arg1"].asUInt();
	uint32_t mId = m_jv["arg2"].asUInt();
	uint32_t status = m_jv["arg3"].asUInt();

	Player * _player = CMapPlayerManger::GetInstance().GetPlayerByPlayerID(playerid);
	if (_player == nullptr)
	{
		return;
	}

	if (types == 1)
	{
		_player->SetPetId(mId);
		if (status == 0)
		{
			_player->SetPetId(0);
		}
	//	_player->SetUpdateInfoFlag(UpdatePlayerInfoType::pet);
	}
	// 坐骑
	else if (types == 2)
	{
		_player->SetMountsId(mId);
		_player->SetMountsState(status);
	//	_player->SetUpdateInfoFlag(UpdatePlayerInfoType::mount);
	}

	_safe_guard_end;
}

// 登录时 比登录消息提前处理，所以同步英雄属性失败
void CMapLogic::OnMsgPlayerHeroInfoChangeRequest(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	_safe_guard_begin;
	Json::Value m_jv = msg.GetJsonValue();
	uint32_t account = m_jv["account"].asUInt();
	uint32_t playerid = m_jv["playerId"].asUInt();
	uint32_t heroid = m_jv["heroId"].asUInt();
	uint32_t heroskinid = m_jv["heroSkinId"].asUInt();
	uint32_t set_type = m_jv["set_type"].asUInt();

	Player * _player = CMapPlayerManger::GetInstance().GetPlayerByPlayerID(playerid);
	if (_player == nullptr)
	{
		return;
	}
	if (_player->GetHeroId() != heroid)
	{
		_player->SetHeroId(heroid);
		//		_player->SetUpdateInfoFlag(UpdatePlayerInfoType::heroId);
	}
	if (heroskinid > 0 && _player->GetHeroSkinId() != heroskinid)
	{
		_player->SetHeroSkinId(heroskinid);
		//		_player->SetUpdateInfoFlag(UpdatePlayerInfoType::heroSkinId);
	}

	switch (set_type)
	{
	case 1:
		_player->SetOneHeroInfo(heroid, m_jv);
		break;
	case 2:
		_player->ResetOneHeroInfo(heroid, m_jv);
		break;
	default:
		break;
	}

	_safe_guard_end;
}

void CMapLogic::OnMsgG2MHeartRequest(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	Json::Value response;
	response["msgid"] = M2G_HEART_RET;
	std::string res = JsonWriter(response);
	send_response_msg(head, M2G_HEART_RET, res);
}

void CMapLogic::OnMsgSendPlayerLoginInfo(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	std::string playerinfo = JsonWriter(m_jv);
	CMapPlayerManger::GetInstance().UpdateLoginPlayerInfo(playerinfo);
}

void CMapLogic::PlayerLoginAgainReq(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	int32_t gate_fd = m_jv["_gate_fd"].asInt();
	
	CMapLogic::GetInstance().PlayerLoginMapServerRequest(gate_fd, msg);
}
void CMapLogic::PlayerLoginMapServerRequest(int32_t fd, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	const Json::Value& m_jv = msg.GetJsonValue();
	LOG_INFO("default", "Player login map server start: 1");

	uint32_t _accountId = m_jv["account"].asUInt();
	uint32_t _playerId = m_jv["playerId"].asUInt();
	uint32_t _area_id = m_jv["_area_id"].asUInt();
	if (_accountId <= 0 || _playerId <= 0 )
	{
		LOG_WARN("default", "Player login map server message error. no 'account'.");
		return;
	}
	
	uint32_t _playerLv = m_jv["playerlv"].asUInt();
	uint32_t _heroId = m_jv["heroId"].asUInt();
	uint32_t _skinId = m_jv["skinId"].asUInt();

	Player* player = CMapPlayerManger::GetInstance().GetPlayerByPlayerID(_playerId);
	if (player == NULL)
	{
		player = CMAPObjManager::GetInstance().CreateObject< Player >(OBJTYPE_PLAYER);
	}
	else
	{
		// 断开原来的连接！!
	}
	
	if ( player == NULL )
	{
		LOG_ERROR("default", "create map player err!!!");
		return;
	}

	// 设置端口ID
	player->SetSocketId(fd);

	// 设置属性
	player->SetPlayerId(_playerId);
	player->SetLevel(_playerLv);
	player->SetObjectType((GameObjectType)OBJTYPE_PLAYER);
	player->SetHeroId(_heroId);
	player->SetHeroSkinId(_skinId);

	player->SetKey(player_key_start + _playerId);

	// 设置默认场景ID
	uint32_t sceneId = (uint32_t)SCENE_MAP_ID::MAIN_CITY;
// 	player->SetSceneId(sceneId);
// 	player->SetPosX(35.92);
// 	player->SetPosY(0.12);
// 	player->SetPosZ(39.71);

	CMapPlayerManger::GetInstance().PlayerEnterGame(*player);
	CMapPlayerManger::GetInstance().RegistePlayerSocket(fd, player->get_id());


		/*设置相关信息*/
	player->SetPingTime(0, 0);

		// 设置玩家信息
	std::string strplayerInfo = CMapPlayerManger::GetInstance().GetLoginPlayerInfo(_playerId);
	Json::Value jm;
	jm.clear();
	JsonReader(strplayerInfo, jm);
	player->SetAccount(jm["account"].asUInt());
	player->SetPlayerId(jm["playerId"].asUInt());
	player->SetName(jm["name"].asString().c_str());
	player->SetArea(_area_id >0 ? _area_id : jm["area"].asUInt());
	player->SetPhoto(jm["photo"].asUInt());
	player->SetPhotoFrame(jm["photoFrame"].asUInt());
	player->SetLevel(jm["level"].asUInt());
	player->SetHeroId(jm["heroId"].asUInt());
	player->SetCurrHeroLevel(jm["heroLevel"].asUInt());
	player->SetHeroSkinId(jm["heroSkinId"].asUInt());
	player->SetVip(jm["vip"].asUInt());
	player->SetUnionId(jm["unionId"].asUInt());
	player->SetUnionName(jm["unionName"].asString().c_str());
	player->SetUnionPosition(jm["unionPosition"].asUInt());
	player->SetPetId(jm["petId"].asUInt());
	player->SetMountsId(jm["mountsId"].asUInt());
	player->SetDefPetId(jm["defPetId"].asUInt());
	player->SetDefMountsId(jm["defMountsId"].asUInt());

	
	if (m_jv["hero_property"].size()) {
		Json::Value hero_json = m_jv["hero_property"];
		player->SetOneHeroInfo(_heroId, hero_json);
	}
	// 发送map登录结果
	player->SendPlayerLoginMapSrvResult();
	// 进入主城
	//player->Send2CEnterScene(player->GetSceneId(), player->GetPosX(), player->GetPosY(), player->GetPosZ());

	LOG_INFO("default", "Player login map server finish.");


	_safe_guard_end;
}

void CMapLogic::SLoseBlood(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	LOG_DEBUG("default", "Game server player lose blood print.");

	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _sor_key = m_jv["sk"].asUInt();//玩家场景ID
	uint32_t _tar_key = m_jv["tk"].asUInt();//怪物场景ID--如果添加[人杀人玩法]，须在下级接口调用中进行判断
	int32_t  _blood = m_jv["hp"].asInt();
	uint32_t  _skill_id = m_jv["sd"].asUInt();
	double _base_value = m_jv["bv"].asDouble();

	if (0 == _blood)
	{
		return;
	}

	if (0 == _tar_key || player.GetKey() == _tar_key)
	{
		//	_tar_key为0，则指用户自己
		player.ModifyHp(_sor_key, _tar_key, _blood);
	}
	else
	{
		// 		Map* _map = player.GetMapPtr();
		// 		_safe_check(_map);

		CSceneInstance* ins = CSceneManager::GetInstance().GetSceneInstance(player.instance_id());
		if (ins == NULL)
		{
			return;
		}


		//		_map->ModifyElementHp(_sor_key, _tar_key, _blood);
		CEntity * entity_mon = ins->GetCreaturesEnityByKey(_tar_key);
		if (entity_mon != NULL) {
			CDamageAction40::ActionEffectForMonster(*entity_mon, player.GetKey(), _blood);
		}

	}

	//player.BroadcastLoseBlood(_sor_key, _tar_key, _skill_id, 0, _base_value);

	_safe_guard_end;
}

void CMapLogic::SPlayerRevive(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;
	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _sor_key = m_jv["sk"].asUInt();
	uint32_t _tar_key = m_jv["tk"].asUInt();
	int32_t _revive_type = m_jv["rt"].asInt();

	if (0 == _tar_key)
	{
		//	_tar_key为0，则指用户自己
		player.Revive(_sor_key, _tar_key, _revive_type);

		// send to game
		Json::Value game_msg;
		game_msg["msgid"] = M2G_REVIVE_EVENT;
		game_msg["ret"] = ::common::SUCCEED;
		game_msg["playerId"] = player.GetPlayerId();
		game_msg["sk"] = _sor_key;
		game_msg["tk"] = _tar_key;
		game_msg["rt"] = _revive_type;

		std::string msg_str = JsonWriter(game_msg);
		send_2_game(M2G_REVIVE_EVENT, msg_str, player.GetArea());
	}
	else
	{

	}

	//pplayer->BroadcastLoseBlood(_sor_key, _tar_key, _skill_id, 0, _base_value);

	_safe_guard_end;
}

void CMapLogic::SPingFromGame(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _key = m_jv["key"].asUInt();
	uint32_t _ch = m_jv["ch"].asUInt();
	uint32_t _cl = m_jv["cl"].asUInt();
	uint32_t playerId = m_jv["playerId"].asUInt();

	Player* player = CMapPlayerManger::GetInstance().GetPlayerByPlayerID(playerId);

	if (player == NULL) {
		return;
	}

	player->SetPingTime(_ch, _cl);

	_safe_guard_end;
}

void CMapLogic::SHeal(Player& player, const CJsonMessageBase& msg)
{
	_safe_guard_begin;

	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	int32_t  _blood = m_jv["arg1"].asInt();

	//pplayer->PlayerHeal(_blood);
	player.PlayerHeal(_blood);

	//pplayer->BroadcastLoseBlood(_sor_key, _tar_key, _skill_id, 0, _base_value);

	_safe_guard_end;
}